package com.th.coupon.executor;

import com.alibaba.fastjson.JSON;
import com.th.coupon.common.vo.GoodsInfo;
import com.th.coupon.common.vo.SettlementInfo;
import org.apache.commons.collections4.CollectionUtils;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 规则执行器的抽象，定义通用方法
 * @author 涂航
 */
public abstract class AbstractRuleExecutor {

    /**
     * 效验商品与优惠卷是否匹配
     * ps：1.这里实现单品类优惠卷的效验，多品类优惠卷重载此方法
     * 2.商品只需要有一个优惠卷要求的商品类型去匹配就可以
     * @param settlementInfo
     * @return
     */
    protected Boolean isGoodsTypeSatisfy(SettlementInfo settlementInfo){
        //获取商品类型
        List<Integer> goodsType =
                settlementInfo.getGoodsInfos().stream().map(GoodsInfo::getType).collect(Collectors.toList());
        //获取单张优惠卷的商品类型
        List<Integer> templateGoodsType = JSON.parseObject(
                settlementInfo.getCouponAndTemplateInfos().get(0).getTemplateSdk().getRule().getUsage().getGoodsType(),
                List.class
        );
        //存在交集
        return CollectionUtils.isNotEmpty(
          CollectionUtils.intersection(goodsType,templateGoodsType)
        );
    }

    /**
     * 处理商品类型与优惠卷限制不匹配的情况
     * @param settlementInfo {@link SettlementInfo} 用户传递的结算信息
     * @param goodsSum 商品总价
     * @return
     */
    protected SettlementInfo processGoodsTypeNatSatisfy(SettlementInfo settlementInfo,
                                                        Double goodsSum){
        Boolean isGoodsTypeSatisfy = isGoodsTypeSatisfy(settlementInfo);
        //当商品类型不满足时，直接返回总价，并清空优惠卷
        if(!isGoodsTypeSatisfy){
            settlementInfo.setCost(goodsSum);
            settlementInfo.setCouponAndTemplateInfos(Collections.emptyList());
            return settlementInfo;
        }

        return null;
    }


    /**
     * 计算商品总价
     * @param goodsInfos
     * @return
     */
    protected Double goodsCostSum(List<GoodsInfo> goodsInfos){
        return goodsInfos
                .stream()
                .mapToDouble(goodsInfo -> goodsInfo.getPrice()*goodsInfo.getCount())
                .sum();
    }

    /**
     * 保留小数
     * @return
     */
    protected Double retain2Decimals(Double value,Integer place){
        return new BigDecimal(value).setScale(place,BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 返回最小支付费用
     * @return
     */
    protected Double minCost(){
        return 0.1;
    }
}
